import Asserts from "@/lang/core/asserts.js";

/**
 * 事件元素
 */
class EventItem {
    constructor(name) {
        /**
         * 事件名称
         */
        this.name = name;
        /**
         * 侦听函数
         * @type {function[]}
         */
        this.listeners = [];
    }
}

/**
 * 数据总线
 */
export default class Eventbus {

    /**
     * 已经被使用的内置事件
     */
    static EVENT = {
        /**
         * 全局事件：打开相册框
         */
        ALBUM: "album"
    }

    /**
     * 事件列表
     * @type {[EventItem]}
     */
    static array = [];

    /**
     * 注册事件
     *
     * @param name {String} 事件名称
     * @param listener {function} 事件侦听
     */
    static registry(name, listener) {
        Asserts.notBlank(listener, 'event listener is undefined!')

        let arr = this.array;

        // 尝试寻找存在的事件
        for (let i = 0; i < arr.length; i++) {
            if (arr[i].name === name) {

                // 避免重复注册事件
                let list = arr[i].listeners;
                for (let j = 0; j < list.length; j++) {
                    if (list[j] === listener) {
                        return;
                    }
                }

                list.push(listener);
                return;
            }
        }

        // 未找到事件则开始新建
        let event = new EventItem(name);
        event.listeners.push(listener);
        arr.push(event);
    }


    /**
     * 解除事件侦听
     * @param name {String} 事件名称
     * @param listener {function| undefined} 事件侦听
     */
    static unregister(name, listener = undefined) {
        if (listener === undefined) {
            this.remove(name);
        } else {
            let arr = this.array;
            for (let i = 0; i < arr.length; i++) {
                if (arr[i].name === name) {

                    let list = arr[i].listeners;
                    for (let j = 0; j < list.length; j++) {
                        if (list[i] === listener) {
                            list.splice(j, 1);
                            break;
                        }
                    }
                    break;
                }
            }
        }
    }

    /**
     * 注册事件
     * @param name {String} 事件名称
     * @param args {any}     消息对象
     */
    static post(name, args) {
        let arr = this.array;

        // 尝试寻找存在的事件
        for (let i = 0; i < arr.length; i++) {
            if (arr[i].name === name) {

                // 避免重复注册事件
                let list = arr[i].listeners;
                for (let j = 0; j < list.length; j++) {
                    // 不要 try...catch... 一个地方出错，终止后续所有事件，
                    // 代码上，并不觉得一个地方报错，其他地方还能正常
                    list[j](args);
                }
                return;
            }
        }
    }

    /**
     * 清除所有事件侦听
     *
     * 前端一般不需要移除事件，事件一般在打开的时候增加侦听事件，
     * 如果未关闭界面，被强行删除，界面不会自动重新注册，需要等刷新后才能恢复。
     *
     * @param name {String} 事件名称
     */
    static remove(name) {
        let arr = this.array;
        for (let i = 0; i < arr.length; i++) {
            if (arr[i].name === name) {
                arr.splice(i, 1);
                break;
            }
        }
    }

    /**
     * 是否包含事件侦听器
     *
     * @param name {String} 事件名称
     */
    static contain(name) {
        let arr = this.array;
        for (let i = 0; i < arr.length; i++) {
            if (arr[i].name === name) {
                return true;
            }
        }
    }

    /**
     * 打开相册
     *
     * @param url{[string]|string}    图片地址列表
     * @param index{number}     展开的图片序号
     */
    static openAlbum(url, index = 0) {
        if (typeof url === 'string') {
            this.post(this.EVENT.ALBUM, {urls: url.split(','), index: index});
        } else {
            this.post(this.EVENT.ALBUM, {urls: url, index: index});
        }
    }

    /**
     * 注册相册
     * @param fun {function} 相册调用事件
     */
    static registryAlbum(fun) {
        this.registry(this.EVENT.ALBUM, fun);
    }

    /**
     * 解除注册相册
     * @param fun {function} 相册调用事件
     */
    static unregisterAlbum(fun) {
        this.unregister(this.EVENT.ALBUM, fun);
    }
}